# coding:utf-8
from __future__ import annotations

from typing import Dict, List, Optional, Union

from pydantic import BaseModel, Field

from apitest.engine.const.enums import Env, IDC, RuleType


class Cookie(BaseModel):
    sessionid: Optional[str]
    fw_account_session_key: Optional[str]

    class Config:
        extra = "allow"


class Token(BaseModel):
    owner: Optional[str]

    class Config:
        extra = "allow"


class FwBusiness(BaseModel):
    fw_account_type: Optional[int]
    fw_account_id: Optional[str]
    fw_account_name: Optional[str]


class PSMAuth(BaseModel):
    psm: Optional[int]
    phone: Optional[int]
    code: Optional[int]
    password: Optional[str]
    user_id: Optional[int]
    fw_user_id: Optional[str]
    fw_business: Optional[FwBusiness]
    email: Optional[str]
    cookie: Optional[Cookie] = Cookie()
    token: Optional[Token] = Token()
    other: Optional[Dict[str, str]]


class TrafficEnv(BaseModel):
    Open: Optional[bool]
    Env: Optional[str]
    ...


class BaseResp(BaseModel):
    StatusMessage: Optional[str]
    StatusCode: Optional[int]
    Extra: Optional[Dict[str, str]]
    ...


class Base(BaseModel):
    LogID: Optional[str]
    Caller: Optional[str]
    Addr: Optional[str]
    Client: Optional[str]
    TrafficEnv: Optional[TrafficEnv]
    Extra: Optional[Dict[str, str]]
    ...


class IDCHost(BaseModel):
    all: str
    lf: Optional[str]
    hl: Optional[str]
    lq: Optional[str]
    sinf: Optional[str]
    boe: Optional[str]

    class Config:
        extra = "allow"


class Item(BaseModel):
    class Config:
        extra = "allow"


class AuthMode(BaseModel):
    header: Optional[Item]
    cookie: Optional[Item]


class PSMConfFromYaml(BaseModel):
    Host: IDCHost
    phone: Optional[int]
    auth: Optional[AuthMode]


class Common(BaseModel):
    env: Optional[str]
    env_label: Optional[str]
    app_id: Optional[int]


class IDLRepoConfig(BaseModel):
    repo_name: str
    file_path: str


class FilterRule(BaseModel):
    """
    regular:
        - rule_code: str
    keywords:
        - rule_code: List[str] or str
    tables:
        - rule_code: List[str]
    """
    rule_type: RuleType
    rule_code: Union[List[str], str]


class EnvModel(BaseModel):
    region: Env
    idc: Optional[IDC]
    env_tag: Optional[str]


class IDLCodeBase(BaseModel):
    repo_name: str
    file_path: str


class DataBase(BaseModel):
    name: Optional[str]
    host: Optional[str]
    port: Optional[str]
    psm: Optional[str]
    user: Optional[str]
    password: Optional[str]


class OAuthMode(BaseModel):
    app_id: Optional[int]
    app_secret: Optional[str]
    owner: Optional[str]
    token: Optional[str]

    class Config:
        extra = "allow"


class AppAuthMode(BaseModel):
    header: Optional[Dict[str, Optional[Dict[Env, str]]]]
    cookie: Optional[Dict[str, Optional[Dict[Env, str]]]]


class AppConfig(BaseModel):
    apply_psm: Optional[List[str]]
    host: Optional[Dict[IDC, str]]
    auth: Optional[AppAuthMode]


class ApiTTConfig(BaseModel):
    env: Optional[EnvModel]
    app: Optional[Dict[str, AppConfig]]
    db: Optional[Dict[str, Dict[Env, DataBase]]]
    idl: Optional[Dict[str, IDLCodeBase]]

    class Config:
        extra = "allow"


class Auth(BaseModel):
    cookie: Optional[Dict[str, str]] = Field(default=dict())
    oauth: Optional[Dict[str, str]] = Field(default=dict())
